package com.king.java.tools.network.impl;

import com.king.java.tools.network.NetworkUtils;
import com.king.java.tools.network.entity.NetworkInfo;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * 描述: 网络设备信息获取工具
 *
 * @author : sujinchen
 * @date : 2020/10/11
 */
public class GeneralNetworkUtils implements NetworkUtils {
    /**
     * 保存机器上的所有网络设备接口
     */
    private List<NetworkInterface> networkInterfaceList = new ArrayList<NetworkInterface>();


    /**
     * 获取机器上的所有网络设备接口
     *
     * @return List<NetworkInterface>
     */
    @Override
    public List<NetworkInterface> getAllNetworkInterfaces() {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            this.networkInterfaceList = getNetworkInterfaces(networkInterfaces);

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return networkInterfaceList;
    }


    /**
     * 获取所有网络设备接口的基本信息
     *
     * @return List<NetworkInfo>
     */
    @Override
    public List<NetworkInfo> getAllNetworkInterfaceInfo() {
        List<NetworkInfo> networkInfos = new ArrayList<NetworkInfo>();
        List<NetworkInterface> allNetworkInterfaces = getAllNetworkInterfaces();
        for (NetworkInterface networkInterface :
                allNetworkInterfaces) {
            NetworkInfo networkInfo = new NetworkInfo();
            networkInfo.setName(networkInterface.getName());
            networkInfo.setDisplayName(networkInterface.getDisplayName());
            networkInfo.setIndex(networkInterface.getIndex());
            try {
                networkInfo.setUp(networkInterface.isUp());
                networkInfo.setLookback(networkInterface.isLoopback());
                networkInfo.setMTU(networkInterface.getMTU());
                networkInfo.setMAC(toHexByte(networkInterface.getHardwareAddress()));
                networkInfo.setPointToPoint(networkInterface.isPointToPoint());
                networkInfo.setSupportsMulticast(networkInterface.supportsMulticast());
            } catch (SocketException e) {
                networkInfo.setUp(false);
                networkInfo.setLookback(false);
                networkInfo.setMTU(-1);
                networkInfo.setMAC(null);
                networkInfo.setPointToPoint(false);
                networkInfo.setSupportsMulticast(false);
                e.printStackTrace();
            }
            networkInfo.setVirtual(networkInterface.isVirtual());
            networkInfo.setParent(networkInterface.getParent());
            networkInfo.setChilds(getNetworkInterfaces(networkInterface.getSubInterfaces()));
            networkInfo.setIP(getInetAddress(networkInterface.getInetAddresses()));
            networkInfos.add(networkInfo);
        }
        return networkInfos;
    }


    /**
     * MAC地址转换，10进制转16进制
     *
     * @param hardwareAddress
     * @return
     */
    private String[] toHexByte(byte[] hardwareAddress) {
        if (hardwareAddress != null) {
            int len = hardwareAddress.length;
            String[] hex = new String[len];
            for (int i = 0; i < len; i++) {
                byte ten = hardwareAddress[i];
                String s = Integer.toHexString(ten);
                if (s.startsWith("ffffff")) {
                    s = s.substring(6);
                }
                if (s.length() == 1) {
                    s = "0" + s;
                }
                hex[i] = s.toUpperCase();
            }
            return hex;
        } else {
            return null;
        }

    }

    /**
     * 获取可用的网络接口信息
     *
     * @return
     */
    @Override
    public List<NetworkInfo> getUsefulNetworkInfo() {
        List<NetworkInfo> networkInfos = new ArrayList<NetworkInfo>();

        List<NetworkInfo> allNetworkInterfaceInfo = getAllNetworkInterfaceInfo();
        for (NetworkInfo networkInfo :
                allNetworkInterfaceInfo) {
            if (networkInfo.getMAC() != null && networkInfo.getIP() != null && networkInfo.getUp()) {
                networkInfos.add(networkInfo);
            }
        }
        if (networkInfos.size() == 0) {
            NetworkInfo networkInfo = new NetworkInfo();
            networkInfo.setName("当前无正常工作的网卡设备");
            networkInfos.add(networkInfo);
        }
        return networkInfos;
    }


    /**
     * 获取网络接口
     *
     * @param networkInterfaces 网络接口枚举
     * @return List<NetworkInterface>
     */
    private List<NetworkInterface> getNetworkInterfaces(Enumeration<NetworkInterface> networkInterfaces) {
        List<NetworkInterface> networkInterfaceList = new ArrayList<NetworkInterface>();
        if (networkInterfaces != null) {
            while (networkInterfaces.hasMoreElements()) {
                networkInterfaceList.add(networkInterfaces.nextElement());
            }
        }
        return networkInterfaceList;
    }

    /**
     * 获取IP地址
     *
     * @param inetAddresses IP地址枚举
     * @return List<InetAddress>
     */
    private List<InetAddress> getInetAddress(Enumeration<InetAddress> inetAddresses) {
        List<InetAddress> inetAddressList = new ArrayList<>();
        if (inetAddresses == null) {
            return inetAddressList;
        }
        while (inetAddresses.hasMoreElements()) {
            inetAddressList.add(inetAddresses.nextElement());
        }
        return inetAddressList;
    }

    /**
     * 获取正在使用得IP地址
     *
     * @param isIPv4
     * @return
     */
    private List<InetAddress> getUsefulIP(boolean isIPv4) {
        List<NetworkInfo> usefulNetworkInfo = getUsefulNetworkInfo();
        List<InetAddress> IPs = new ArrayList<>();
        for (NetworkInfo info :
                usefulNetworkInfo) {
            List<InetAddress> ip = info.getIP();
            if (ip != null) {
                InetAddress IP = null;
                if (isIPv4) {
                    IP = ip.get(0);
                } else {
                    IP = ip.get(0);
                }
                IPs.add(IP);
            }
        }
        return IPs;
    }

    /**
     * 获取可用的IPv4地址
     *
     * @return
     */
    @Override
    public List<InetAddress> getUsefulIPv4() {
        return getUsefulIP(true);
    }

    /**
     * 获取可用的IPv6地址
     *
     * @return
     */
    @Override
    public List<InetAddress> getUsefulIPv6() {
        return getUsefulIP(false);
    }

}
